package com.bwie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bwie.config.FastFileUtil;
import com.bwie.config.FreemarkerUtil;
import com.bwie.mapper.RecordsMapper;
import com.bwie.mapper.VoteMapper;
import com.bwie.pojo.TbRecords;
import com.bwie.pojo.TbVote;
import com.bwie.service.VoteService;
import com.bwie.utils.R;
import com.bwie.vo.MessageVo;
import com.bwie.vo.PageVo;
import com.rabbitmq.client.Channel;
import freemarker.template.TemplateException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

/**
 * @Title:
 * @BelongProjecet zk2
 * @BelongPackage com.bwie.service.impl
 * @Description:
 * @Copyright 研发一部
 * @Author: Mr.yan
 * @Date: 2024/6/4 8:53
 * @Version V1.0
 */
@Service
public class VoteServiceImpl implements VoteService {

    @Autowired
    private VoteMapper voteMapper;
    @Autowired
    private FastFileUtil fastFileUtil;
    @Autowired
    private RecordsMapper recordsMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void  rabbitInit(){
        System.out.println("本少爷要开始启动了");
        //如果发送失重新发送一次
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                //发送失败重新发送
                String s3 = new String(message.toString());
                rabbitTemplate.convertSendAndReceive(s1,s2,s3);
            }
        });

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                if (b){
                    System.out.println("发送成功");
                }else {
                    System.out.println("发送失败");
                }
            }
        });
    }

    @Override
    @Transactional
    public R addVoter(TbVote tbVote) {
        //1.添加报名人信息
        voteMapper.insert(tbVote);
        // //2.判断是否添加成功
        // if (addVote > 0 ){
        //     //将添加的对象转换为map
        //     HashMap<String, Object> toMap = (HashMap<String, Object>) BeanUtil.beanToMap(tbVote);
        //     //获取当前项目路径
        //     String html = this.getClass().getResource("/").getPath();
        //     FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
        //     try {
        //         String utilHtml = freemarkerUtil.createHtml(toMap, "vote", html + "vote2111A");
        //         if (StringUtil.isEmpty(utilHtml)){
        //             throw new RuntimeException("生成html失败");
        //         }
        //         File file = FileUtil.file(utilHtml);
        //         String url = fastFileUtil.uploadFile(file);
        //         tbVote.setUrl(url);
        //         voteMapper.updateById(tbVote);
        //     } catch (Exception e) {
        //         throw new RuntimeException(e);
        //     }


        return R.success();
    }

    @Override
    public R voteList(PageVo pageVo) {
        Page<TbVote> page = new Page<>(pageVo.getPageNum(), pageVo.getPageSize());
        IPage<TbVote> voteList = voteMapper.voteList(page);
        return R.success(voteList);
    }

    @Override
    public R findByVote(Integer id, String token) throws TemplateException, IOException {
        //1.通过id查询报名人信息
        TbVote tbVote = voteMapper.selectOne(
                new QueryWrapper<TbVote>().lambda().eq(TbVote::getId, id)
        );
        if (tbVote == null){
            return R.error(500,"该用户未存在");
        }

        tbVote.setToken(token);
        //2.生成静态页面
        FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
        HashMap<String, Object> map = new HashMap<>();
        map.put("tbVote",tbVote);
        String html = freemarkerUtil.createHtml(map, "vote", "C:\\freemaker\\" + UUID.randomUUID().toString() + ".html");
        // FastFileUtil fastFileUtil = new FastFileUtil();
        String file = fastFileUtil.uploadFile(new File(html));
        return R.success(file);
    }

    @Override
    public R addRecords(Integer tbVote, String token) {
        //1.解析token，获取当前投票人的id
        Claims claims = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody();
        Integer userId = claims.get("id", Integer.class);

        //2.添加点赞记录表
        TbRecords tbRecords = new TbRecords();
        tbRecords.setUserId(userId);
        tbRecords.setVoteId(tbVote);
        tbRecords.setStartTime(new Date());

        //3.通过mq发送消息
        MessageVo messageVo = new MessageVo();
        //生成唯一标识
        String msgId = "msg-"+UUID.randomUUID().toString();
        messageVo.setMessageId(msgId);
        //将记录信息存放到vo中
        String records = JSON.toJSONString(tbRecords);
        messageVo.setMessageBody(records);

        //将信息存入redis中，防止重复消费
        String message = JSON.toJSONString(messageVo);
        stringRedisTemplate.opsForValue().set(msgId,message);

        //发送消息
        rabbitTemplate.convertSendAndReceive("directExchange","toRecordBind",message);

        // recordsMapper.insert(tbRecords);
        return R.success();
    }


    @RabbitListener(queues = "recordsQueue")
    public void addRecords(Message message, Channel channel){
        try {
            //1.接受发送过来的参数
            String s = new String(message.getBody());
            //2.判断是否消费过
            MessageVo messageVo = JSON.parseObject(s, MessageVo.class);
            String messageId = messageVo.getMessageId();
            if (!stringRedisTemplate.hasKey(messageId)){
                System.out.println("已经消费过了，不能重复消费");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
                return;
            }

            //3.添加投票记录表
            String messageBody = messageVo.getMessageBody();
            TbRecords tbRecords = JSON.parseObject(messageBody, TbRecords.class);
            recordsMapper.insert(tbRecords);

            //4.消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);

            //5.删除缓存，防止重复消费
            stringRedisTemplate.delete(messageId);

            System.out.println("消费成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
